package server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Vector;

import ssl.SecureSocket;
import ssl.SecureSocketClient;
import tunnel.LocalSocket;
import tunnel.RemoteSocket;

public class ServerRSAConnection extends Thread {
	
	ServerSocket localSocket;
	RemoteSocket remoteSocket;
	
	public ClientKeys cKeys;
	KeyPair serverKeyPair;
	
	public static Vector<Integer> desPorts;
	
	static LocalSocket tunnel;
	
	public ServerRSAConnection(KeyPair serverKeyPair) {
		this.serverKeyPair = serverKeyPair;
		init();
		try {
			localSocket = new ServerSocket(7777);
		} catch (IOException e) {
			System.out.println("Konnte lokalen Server nicht aufmachen");
			e.printStackTrace();
		}
	}
	
	public void init() {
		try {		
			cKeys = new ClientKeys();
			cKeys.readKeys();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
		
	
	@Override
	public void run() {
		while(true) {
			try {
				Socket client = localSocket.accept();
				InputStream  in  = client.getInputStream();
				
				byte[] received=new byte[9000];
				int length = in.read(received);
				
				String command = DecodeRSA(received, length, serverKeyPair.getPrivate());
				System.out.println("RSA: Empfangen: " + command);
				
				String[] strings = command.split(" ");
				
				if(strings.length == 3) {
					String befehl = strings[0];
					
					if(befehl.equals("auth")) {
						String username = strings[1];
						String pwhash = strings[2];
						System.out.println("Gefundenes Passwort: " + pwhash);
						
						int pos;
						if((pos=cKeys.inList(username)) != -1) {
							ClientKey cKey = cKeys.keys.get(pos);
							
							if(Arrays.equals(cKey.pwhash.getBytes(),pwhash.getBytes())) 
							{
								
								String random = DUMMYGenerateSecureRandom();
								OutputStream out = client.getOutputStream();
								
								String antwort = "auth_ok " + random;
								
								byte[] antwort_ecrypt = EncodeRSA(antwort, cKey.key.getPublic());
								System.out.println("RSA: Sende: " + antwort);
								
								out.write(antwort_ecrypt);
								out.flush();
								
								//Tunnel mit Random starten
								if(tunnel != null) {
									tunnel.stopTunnel();
									while(tunnel.isAlive()); // Warten, dass Tunnel beendet ist.
								}
								tunnel = new LocalSocket(8888, "127.0.0.1", 80, random, client.getInetAddress().getHostAddress(), LocalSocket.MODE_SERVER);
								tunnel.start();
							} else {
								System.out.println("Falsches Passwort, gefordet: " + cKey.pwhash);
							}
						} else {
							System.out.println("Benutzer nicht gefunden");
						}
					}
				}
				
				client.close();

			} catch (IOException e) {
				System.out.println("TimeOut beim warten auf lokale Verbindung");
				e.printStackTrace();
			}

		}
	}
	


	private byte[] EncodeRSA(String antwort, PublicKey pubKey) {
		byte[] bytes = SecureSocket.encrypt(antwort.getBytes(), pubKey, "RSA");
		return bytes;
	}

	private String DUMMYGenerateSecureRandom() {
		return SecureSocket.generatePasswords(1, 8)[0];
	}

	private String DecodeRSA(byte[] received, int length, PrivateKey key) {
		if(length > 0) {
			System.out.println("Entschl�ssle RSA der L�nge: " + length);
			byte[] decode = new byte[length];
			for(int i=0;i<length;i++) {
				decode[i] = received[i];
			}
			byte[] bytes = SecureSocketClient.decrypt(decode, key, "RSA");
			
			return new String(bytes);
		}
		return "";
	}

}